package com.whz.compare;

import java.util.Comparator;
import static java.util.Comparator.comparingInt;

/**
 * @ClassName PhoneNumber
 * @Description TODO
 * @Author hong-zhi
 * @Date 2021/5/3 17:15
 * @Version 1.0
 */
public final class PhoneNumber implements Cloneable, Comparable<PhoneNumber> {
    private final short areaCode, prefix, lineNum;
    private int hashCode;
    private static final Comparator<PhoneNumber> COMPARATOR =
                                                            comparingInt((PhoneNumber pn) -> pn.areaCode)
                                                            .thenComparingInt(pn -> pn.prefix)
                                                            .thenComparingInt(pn -> pn.lineNum);
    public static PhoneNumber create(short areaCode, short prefix, short lineNum) {
        return new PhoneNumber(areaCode, prefix, lineNum);
    }

    private PhoneNumber(short areaCode, short prefix, short lineNum) {
        this.areaCode = rangeCheck(areaCode, (short) 999, "area code");
        this.prefix = rangeCheck(prefix, (short) 999, "prefix");
        this.lineNum = rangeCheck(lineNum, (short) 9999, "line num");
    }
    private static short rangeCheck(short val, short max, String arg) {
        if(val < 0 || val > max) {
            throw new IllegalArgumentException(arg + ": " + val);
        }
        return val;
    }

    @Override
    public int hashCode() {
        int result = hashCode;
        if(result == 0) {
            result = Short.hashCode(areaCode);
            result = 31 * result + Short.hashCode(prefix);
            result = 31 * result + Short.hashCode(lineNum);
            hashCode = result;
        }
        return result;
    }

    @Override
    public String toString() {
        return String.format("%03d-%03d-%04d", areaCode, prefix, lineNum);
    }

    @Override
    public PhoneNumber clone() throws CloneNotSupportedException {
        return (PhoneNumber) super.clone();
    }

    @Override
    public int compareTo(PhoneNumber o) {
        return COMPARATOR.compare(this, o);
    }
}
